package com.zzl.mine.tool;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Description：图片工具类
 * Created by 朱正磊 on 2019-04-25 09:53
 */
@SuppressWarnings("restriction")
public class ImageUtil {

    /**
     * description：对图片进行压缩（图片尺寸不变，存储变小）
     * user 朱正磊
     * time 2019-04-25 09:55
     * @param src 源文件绝对路径（全路径）（压缩前）
     * @param to 目的文件绝对路径（全路径）（压缩后）（如果文件不存在会进行创建，包括文件夹）
     * @param quality 图片压缩质量参数（图片压缩质量参数为0.7f，相当于70%质量，压缩掉30%）（大于0.5f基本上不会失真）
     * @return 如果压缩成功返回true，否则返回false
     */
    public static boolean compress(String src, String to, float quality) {
        if (quality > 1 || quality < 0.1) {
            throw new IllegalArgumentException("图片质量需设置在0.1-1范围");
        }
        boolean rs = true;
        JPEGEncodeParam param;
        File destination = new File(to);
        FileOutputStream os = null;
        try {
            BufferedImage image = ImageIO.read(new File(src));
            param = JPEGCodec.getDefaultJPEGEncodeParam(image);
            param.setQuality(quality, false);

            //如果目标文件不存在会进行创建，包括文件夹
            os = FileUtils.openOutputStream(destination);

            JPEGImageEncoder encoder;
            encoder = JPEGCodec.createJPEGEncoder(os, param);
            encoder.encode(image);
        } catch (Exception e) {
            e.printStackTrace();
            rs = false;
        } finally {
            IOUtils.closeQuietly(os);
        }
        return rs;
    }

    /**
     * description：对图片进行缩放（图片尺寸变小，存储也会跟着变小）
     * user 朱正磊
     * time 2019-04-25 09:55
     * @param src 源文件绝对路径（全路径）（缩放前）
     * @param to 目的文件绝对路径（全路径）（缩放后）（如果文件不存在会进行创建，包括文件夹）
     * @param newWidth 指定图片新的宽度（缩放宽度）
     * @param newHeight 指定图片新的高度（缩放高度）
     * @return 如果缩放成功返回true，否则返回false
     */
    public static boolean resize(String src, String to, int newWidth, int newHeight) {
        try {
            //源文件
            File srcFile = new File(src);

            //创建目标文件方法一
            //FileUtils.openOutputStream方法的作用如下解释
            //如果目标文件不存在会进行创建，包括文件夹
            //该方法的作用就是用来创建文件以及文件夹
            //如果没有该方法，文件没有可以创建，文件夹没有就无法创建
            //也就是说如果没有该方法，当目录不存在时会抛找不到文件异常
            /*File toFile = new File(to);
            FileUtils.openOutputStream(toFile);*/

            //创建目标文件方法二（如果目标文件不存在会进行创建，包括文件夹）
            File toFile = FileUtil.createFile(to);

            BufferedImage img = ImageIO.read(srcFile);
            int w = img.getWidth();
            int h = img.getHeight();
            BufferedImage destImg = new BufferedImage(newWidth, newHeight, img.getType());
            Graphics2D g = destImg.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(img, 0, 0, newWidth, newHeight, 0, 0, w, h, null);
            g.dispose();
            ImageIO.write(destImg, "jpg", toFile);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * description：压缩并缩放图片(压缩图片质量，改变图片尺寸)
     * user 朱正磊
     * time 2019-04-25 10:20
     * @param src 原始文件绝对路径（全路径）
     * @param to 缩放文件绝对路径（全路径）（如果文件不存在会进行创建，包括文件夹）
     * @param maxWidth 最大宽度（若原图宽度小于最大宽度，则新宽度就是原图宽度，相当于没有缩放保持原样）
     * @param maxHeight 最大高度（若原图高度小于最大高度，则新高度就是原图高度，相当于没有缩放保持原样）
     * @param quality 图片质量参数（如果图片质量参数为0.7f，相当于压缩到70%质量，压缩掉30%的质量）
     * @throws IOException IO流异常
     */
    public static void imageResize(String src, String to, int maxWidth, int maxHeight, float quality) throws IOException {
        if (quality > 1 || quality < 0.1) {
            throw new IllegalArgumentException("图片质量需设置在0.1-1范围");
        }

        //原始文件（源文件）
        File originalFile = new File(src);
        //缩放文件（目标文件）（如果目标文件不存在会进行创建，包括文件夹）
        File resizedFile = FileUtil.createFile(to);

        ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());
        Image i = ii.getImage();
        Image resizedImage = null;

        int iWidth = i.getWidth(null);
        int iHeight = i.getHeight(null);

        //如果设置的缩放宽度大于了原始宽度，则新宽度就是原始宽度
        int newWidth = maxWidth;
        if (iWidth < maxWidth) {
            newWidth = iWidth;
        }

        //原始宽度大于原始高度，宽度决定高度（也就是说maxHeight将不起作用）
        if (iWidth >= iHeight) {
            resizedImage = i.getScaledInstance(newWidth, (newWidth * iHeight) / iWidth, Image.SCALE_SMOOTH);
        }

        //如果设置的缩放高度大于了原始高度，则新高度就是原始高度
        int newHeight = maxHeight;
        if (iHeight < maxHeight) {
            newHeight = iHeight;
        }

        //原始高度大于原始宽度，高度决定宽度（也就是说maxWidth将不起作用）
        if (resizedImage == null && iHeight >= iWidth) {
            resizedImage = i.getScaledInstance((newHeight * iWidth) / iHeight, newHeight, Image.SCALE_SMOOTH);
        }

        assert resizedImage != null;
        Image temp = new ImageIcon(resizedImage).getImage();

        BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null), temp.getHeight(null), BufferedImage.TYPE_INT_RGB);
        Graphics g = bufferedImage.createGraphics();

        g.setColor(Color.white);
        g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
        g.drawImage(temp, 0, 0, null);
        g.dispose();

        float softenFactor = 0.05f;
        float[] softenArray = {0, softenFactor, 0, softenFactor, 1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0};
        Kernel kernel = new Kernel(3, 3, softenArray);
        ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
        bufferedImage = cOp.filter(bufferedImage, null);

        FileOutputStream out = new FileOutputStream(resizedFile);
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage);
        param.setQuality(quality, true);

        encoder.setJPEGEncodeParam(param);
        encoder.encode(bufferedImage);
    }

    /**
     * description：测试上面的工具方法
     * user 朱正磊
     * time 2019-04-25 10:44
     */
    public static void main(String[] args) {
        //1、测试compress
        /*String src = "C:\\Users\\Public\\Pictures\\Sample Pictures\\7.png";
        String to = "E:\\img\\new\\7.png";
        float quality = 0.8f;
        boolean flag = compress(src, to, quality);
        System.out.println(flag);*/

        //2、测试resize
        /*String src = "C:\\Users\\Public\\Pictures\\Sample Pictures\\7.png";
        String to = "E:\\img\\new\\7.png";
        int newWidth = 50;
        int newHeight = 50;
        boolean flag = resize(src, to, newWidth, newHeight);
        System.out.println(flag);*/

        //3、测试imageResize
        try {
            //原始：502 * 317
            String src = "C:\\Users\\Public\\Pictures\\Sample Pictures\\7.png";
            String to = "E:\\img\\new\\7.png";
            imageResize(src, to, 300, 100, 0.8f);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
